Observables
The observables defined below are defined in the python package qtealeaves. However, it is really helpful to have them reported here, since they are a fundamental element of qmatchatea. Observables define the quantities we are interested in measuring at the end of the simulation, i.e. everything that really interests the user. Remember to always define your observables, otherwise you are probably wasting computational hours.
- class qtealeaves.observables.local.TNObsLocal(name, operator)[source]
The local observable will measure an operator defined on a single site across the complete system. This means that, if the single site has a dimension \(d\) we expect the local observable to be a matrix of dimension \(d\times d\). For example, if we are working with qubits, i.e. \(d=2\), a local observable can be the Pauli matrix \(\sigma_z\).
The local observable will be measured on each site of the tensor network. As such, the output of this measurement will be a dictionary where:
the key is the name of the observable
the value is a list of length \(n\), with \(n\) the number
of sites of the tensor network. The \(i\)-th element of the list will contain the expectation value of the local observable on the \(i\)-th site.
Arguments
- namestr
Define a label under which we can find the observable in the result dictionary.
- operatorstr
Identifier/string for the operator to be measured.
- class qtealeaves.observables.bond_entropy.TNObsBondEntropy[source]
Observable to enable the measurement of the Von Neumann bond entropy at the end of a circuit. If the state is pure, than this measurement is equal to the entanglement. Otherwise it is not well defined. Given a quantum state of \(n\) sites \(|\psi\rangle\) the Von Neumann entropy of the bipartition \(A(B)\) with \(n_{A(B)}\) sites is defined as:
\[S_V(\rho_A) = -\mathrm{Tr} \rho_A\ln(\rho_A), \quad \rho_A=\mathrm{Tr}_B\left( |\psi\rangle\langle\psi|\right)\]This value should be computed using the natural logarithm, i.e. the logarithm in base \(e\).
The output of the measurement will be a dictionary, where:
As keys, we report on continous range of site which form the first bipartition. For example, the continuous range (4, 5) has the bipartitions [4, 5] vs [0, 1, 2, 3, 6, 7]. An MPS will define the first bipartitions in the different cuts as (0, 0), (0, 1), (0, 2), (0, 3), etc.
Indices are python indices starting at zero in the keys.
As value the result of \(S_V\). Natural log is used for both MPS and TTN.
The expression above for the computation of the bond entropy is quite complex. Using tensor network we can strongly simplify it, using the singular values \(s_i\) “stored” in the link. This is equivalent to look at the eigenvalues \(\lambda_i\) of the reduced density matrix \(\rho_A\) for a pure system like MPS and TTN:
\[S_V(\rho_A) = -\sum_{i} \lambda_i \ln(\lambda_i) = -\sum_{i} s_i^2 \ln(s_i^2)\]
- class qtealeaves.observables.projective.TNObsProjective(num_shots, qiskit_convention=False)[source]
Observable to enable the final projective measurements after the evolution. This observable is meant to give single-shot measurements: the system is projectively measured a number of times equal to num_shots, such that the user can observe a statistic of the distribution of the state.
The result of the observable will be a dictionary where:
the keys are the measured state on a given basis
the values are the number of occurrences of the keys in the num_shots single shots measurements
As an example, if we work with qubits, we measure on the computational base and we end up with the state \(\frac{1}{\sqrt{2}}(|00\rangle+|11\rangle)\), requesting 1000 num_shots we will end up with the following result:
{'00' : 505, '11' : 495}. Take into account that the measurement is probabilistic and such is will only be an approximation of the true probability distribution, that in the example case would be \(p_{00}=p_{11}=0.5\).Parameters
- num_shotsint
Number of projective measurements
- qiskit_conventionbool, optional
If you should use the qiskit convention when measuring, i.e. least significant qubit on the right. Default to False.
- class qtealeaves.observables.tensor_product.TNObsTensorProduct(name, operators, sites)[source]
Observables which are tensor product between one-site or two-site operators.
This observable enables the computation of observables of the following form. On a tensor network with \(n\) sites we can measure \(O\) of the form:
\[O = o_0 \otimes o_2 \otimes o_3 \otimes \dots \otimes o_{n-1}\]where the different local observables \(o_i\) might be different or even be the identity.
The output of the measurement will be a dictionary where:
The key is the name of the observable
The value is its expectation value
An example of such an observable is the Parity of the system. If we work on a system of qubits, then to measure the parity we simply have to use \(o_i=o_j=\sigma_z \; \forall \; i,j\in\{0, n-1\}\), where \(\sigma_z\) is the Pauli matrix.
Parameters
- name: str
Name to identify the observable
- operators: list of str or str
Idenitifiers/names for the operators to be measured. If str the same operator is applied to the whole MPS
- sites: list of int or int
Indexes to which the operators should be applied, in the same order. If int instead it is the size of the chain, and the operator is assumed to be applied to each site of the tensor network
- class qtealeaves.observables.weighted_sum.TNObsWeightedSum(name, tp_operators, coeffs, use_itpo=False)[source]
Class to measure observables which is the weighted sum of tensor product, which means of the type
\[O = \sum_{i=0}^m \alpha_i\left( o_1^i\otimes o_2^i \otimes \dots \otimes o_n^i \right)\]where \(m\) is the number of addends and \(n\) the number of sites. For further informations about the single observable \(O_i=o_1^i\otimes o_2^i \otimes \dots \otimes o_n^i\) see the documentation of
TNObsTensorProduct.The output of the measurement will be a dictionary where:
The key is the name of the observable
The value is its expectation value
An example of this observable are Pauli decompositions of Hamiltonian, i.e. Hamiltonians written as a weighted sum of tensor product operators formed by Pauli matrices. They are usually used in the Quantum chemistry applications, such as the Variational Quantum Eigensolver.
Parameters
- name: str
Name to identify the observable
- tp_operators:
TNObsTensorProduct Tensor product observables. Its length, i.e. the number of tensor product observables contained in it, should be the same of the number of complex coefficients.
- coeffs: list of complex
Coefficients of the weighted sum for each tp_operators
- use_itpo: bool, optional
If True, measure using ITPO. Default to False. Consumed in python.
- class qtealeaves.observables.probabilities.TNObsProbabilities(prob_type='U', num_samples=None, prob_threshold=None, precision=15, qiskit_convention=False)[source]
Observable to measure the probabilities of the state configurations at the end of an evolution.
Parameters
- prob_type: str, optional
The type of probability measure. Available: - ‘U’, unbiased (probabilities and count) - ‘G’, greedy (probabilities only) - ‘E’, even. (probabilities only, also implemented in Fortran backend) Default to ‘U’
- num_samples: int | None, optional
“U” only: Number of samples for the unbiased prob_type. If a list is passed, the function is called multiple times with that list of parameters. Default to 100 (via None)
- prob_threshold: float | None, optional
probability treshold for prob_type=(‘G’, ‘E’). Recall that prob_type=E needs lower thresholds to measure more states while prob_type=G needs higher thresholds to measure more states. Default to 0.9 for “G”, 0.1 for “E” (via None)
- precisionint, optional
Decimal place precision for the mpmath package. It is only used inside the function, and setted back to the original after the computations. Before processing the intervals with precision larger than 15 you need to set mpmath precision again. If it is 15 or smaller, it just uses numpy. Default to 15.
- qiskit_conventionbool, optional
If you should use the qiskit convention when measuring, i.e. least significant qubit on the right. Default to False.
Details
The probabilities are computed following a probability tree, where each node is a site, and has a number of childs equal to the local dimension \(d\) of the site. We keep track of the probabilities of the paths from the root to the leaves. The leaves identify the final state. For example, a state written as
\[|\psi\rangle = \sqrt{N}\left(|00\rangle + |01\rangle + 2|11\rangle\right)\]with \(N=\frac{1}{6}\) will have the following probability tree. Branches going left measures \(0\) while branches on the right measures \(1\). The ordering here is the right-most site being the index-0 site.
----o---- # No measure, state s2,s1 p=1/6/ \p=5/6 # First measure, states s2,0 or s2,1 o o p=1/6/ \p=0 p=1/6/ \p=4/6 # Second measure, states 0,0 or 0,1 or 1,1 00 10 01 11
There are three possible ways of computing the probability:
Going down evenly on the tree, which means following ALL possible paths at the same time, and discarding paths which probability is below an input threshold \(\epsilon\). You might have no outputs, if all the branches has a probability \(p<\epsilon\).
Going down greedily on the tree, which means following each time the path with highest probability, until the total probability measured is more then a threshold \(\mathcal{E}\). This procedure is dangerous, since it can take an exponentially-long time if \(\mathcal{E}\) is too high.
Going down unbiasedly on the tree, which means drawing a
num_sumplesuniformly distributed random numbers \(u\sim U(0,1)\) and ending in the leaf which probability interval \([p_{\mathrm{low}}, p_{\mathrm{high}}]\) is such that \(u\in [p_{\mathrm{low}}, p_{\mathrm{high}}]\). This is the suggested method. See http://arxiv.org/abs/2401.10330 for additional details.
The result of the observable will be a dictionary where:
the keys are the measured state on a given basis
the values are the probabilities of measuring the key for the even and greedy approach, while they are the probability intervals for the unbiased approach and the count of each sample, i.e., a tuple of three numbers.
- class qtealeaves.observables.state2file.TNState2File(name, formatting)[source]
Write the state to a file.
We stress that saving the state to a file will enable to further measure observables, since you will have available all the informations you had at the end of the simulation.
Warning
While saving the state can be useful, it can really slow down the evolution when it is saved at each time-step of a time evolution. Please use this observable carefully! Reference to the description on the backend for more specific informations.
Arguments
- namestr
Filename to save the state.
- formattingchar
Specifies format, i.e., ‘F’ for formatted, ‘U’ for unformatted, or ‘D’ for formatted without symmetries. On the python backend, U is pickled, F is formatted D is converted to dense tensor and pickled (especially the last on is different from fortran, where the dense TN is stored as formatted file).
- class qtealeaves.observables.tnobservables.TNObservables(filename_observables='observables.in', folder_observables='observables', num_trajectories=1, do_write_hdf5=False)[source]
Organization of all the measurements to be taken during a tensor network simulation. To add new observables in the container you should simply use the
+=operator as shown in the example.Example
obs = TNObservables() obs += any_other_observable
Arguments
- filename_observablesstr
Base filename of the definition with the observables inside the input folder and observables subfolder. A postfix might be appended upon need. The file extension will be chosen by the backend.
- folder_observablesstr
Subfolder for the observable input files inside the input folder.
- num_trajectoriesint
Total number of quantum trajectories.
Details
Up to now, the class organizes and accepts observables of the type
TNObsLocal,TNObsCorr,TNDistance2Pure,TNState2File,TNObsTensorProduct,TNObsWeightedSum,TNObsProjective,TNObsProbabilities,TNObsBondEntropy,TNObsCustom,TNObsDenseMPOList